﻿using System;
using System.Collections.Generic;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Server;

namespace EAGL.Core
{
    public static class SerializationManager
    {

        public static string XMLSerialize(object obj, string objectName)
        {
            string url = "http://www.esri.com/schemas/ArcGIS/9.0";
            IXMLStream stream = new XMLStreamClass();
            IXMLWriter writer = new XMLWriterClass();
            writer.WriteTo(stream as IStream);
            IXMLSerializer serializer = new XMLSerializerClass();
            serializer.WriteObject(writer, null, null, objectName, url, obj);
            return stream.SaveToString();
        }

        public static object XMLDeSerialize(string objectString)
        {
            IXMLStream stream = new XMLStreamClass();
            stream.LoadFromString(objectString);
            IXMLReader reader = new XMLReaderClass();
            reader.ReadFrom(stream as IStream);
            IXMLSerializer serializer = new XMLSerializerClass();
            object obj = serializer.ReadObject(reader, null, null);
            IPersistStream pstream = obj as IPersistStream;
            return pstream;
        }


        public static byte[] XMLSerializeToBytes(object obj, string objectName)
        {
            string url = "http://www.esri.com/schemas/ArcGIS/9.0";
            IXMLStream stream = new XMLStreamClass();
            IXMLWriter writer = new XMLWriterClass();
            writer.WriteTo(stream as IStream);
            IXMLSerializer serializer = new XMLSerializerClass();
            serializer.WriteObject(writer, null, null, objectName, url, obj);
            return stream.SaveToBytes();
        }

        public static object XMLDeSerializeFromBytes(byte[] objectBytes)
        {
            IXMLStream stream = new XMLStreamClass();
            stream.LoadFromBytes(ref objectBytes);
            IXMLReader reader = new XMLReaderClass();
            reader.ReadFrom(stream as IStream);
            IXMLSerializer serializer = new XMLSerializerClass();
            object obj = serializer.ReadObject(reader, null, null);
            IPersistStream pstream = obj as IPersistStream;
            return pstream;
        }


        public static byte[] SerializeUsingPersistStream(IPersistStream ps)
        {
            IXMLStream xmlStream = new XMLStreamClass();
            ps.Save(xmlStream as IStream, 0);
            byte[] bs = xmlStream.SaveToBytes();
            return bs;
        }

        public static void DeserializeUsingPersistStream(byte[] bytes, ref object o)
        {
            IPersistStream ps = o as IPersistStream;
            if (o == null)
                throw new Exception("Objects doesn't implement IPersistStream");
            IXMLStream xmlStream = new XMLStreamClass();
            xmlStream.LoadFromBytes(ref bytes);
            ps.Load(xmlStream as IStream);
        }

        public static byte[] Serialize(object obj)
        {
            IObjectStream ostrm = new ObjectStreamClass();       
            IXMLStream stream = new XMLStreamClass();
            ostrm.Stream = stream as IStream;
            ostrm.SaveObject(obj);
            byte[] b = stream.SaveToBytes();
            return b;
        }

        public static object Deserialize(byte[] serializedObject, Guid guid)
        {
            IObjectStream ostrm = new ObjectStreamClass();
            IXMLStream stream = new XMLStreamClass();
            ostrm.Stream = stream as IStream;
            stream.LoadFromBytes(ref serializedObject);
            object o = new object();
            o = ostrm.LoadObject(ref guid, null);
            return o;
        }

        public static object DeserializeToServerContext(byte[] serializedObject, Guid guid, IServerContext context)
        {
            IObjectStream ostrm = context.CreateObject("esriSystem.ObjectStream") as IObjectStream;
            IXMLStream stream = context.CreateObject("esriSystem.XMLStream") as IXMLStream;
            ostrm.Stream = stream as IStream;
            stream.LoadFromBytes(ref serializedObject);
            IObject obj = context.CreateObject("esriGeodatabase.Object") as IObject;
            object o = ostrm.LoadObject(ref guid, null);
            return o;  
        }
        
        
        public static void SaveToFile(object obj, string fileName)
        {
            IObjectStream ostrm = new ObjectStreamClass();
            IMemoryBlobStream2 strm = new MemoryBlobStreamClass();
            ostrm.Stream = strm;
            ostrm.SaveObject(obj);
            strm.SaveToFile(fileName);
        }

        public static object LoadFromFile(string fileName, Guid guid)
        {
            IObjectStream ostrm = new ObjectStreamClass();
            IMemoryBlobStream2 strm = new MemoryBlobStreamClass();
            ostrm.Stream = strm;
            strm.LoadFromFile(fileName);
            object o = ostrm.LoadObject(ref guid, null);
            return o;
        }
    }
}
